﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing;
using CircuitBoardApplication.Classes.Components;
using CircuitBoardApplication.Classes.Components.Gates;

namespace CircuitBoardApplication.Classes
{
    class CircuitBoard
    {
        public List<ComponentMain> components;

        public CircuitBoard()
        {
            this.components = new List<ComponentMain>();
            
        }

        // <summary>
        /// If this playground does not have a component with identity id,
        /// then a new plate is created, added to the list thePlates, and the returnvalue is true,
        /// else the returnvalue is false. 
        /// </summary>
        /// <param name="id"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="initialNrOfCookies"></param>
        /// <returns></returns>
        public bool AddComponent(int id, String type, int value, int x, int y, String ElementValue)
        {
            if (this.GetComponent(x, y) == null)
            {
                ComponentMain temp;
                if (type == "GATE")
                {
                    if (ElementValue == "AND")
                    {
                        temp = new gateAND(id, type, value, x, y);
                        this.components.Add(temp);
                        return true;
                    }
                    else if (ElementValue == "OR")
                    {
                        temp = new gateOR(id, type, value, x, y);
                        this.components.Add(temp);
                        return true;
                    }
                    else
                    {
                        temp = new gateNOT(id, type, value, x, y);
                        this.components.Add(temp);
                        return true;
                    }
                }
                else if (type == "SOURCE")
                {
                    if (ElementValue == "1")
                    {
                        temp = new Source(id, type, value, x, y);
                        this.components.Add(temp);
                        return true;
                    }
                }
                else if (type == "SINK")
                {
                    temp = new Sink(id, type, value, x, y);
                    this.components.Add(temp);
                    return true;

                }
            }
            return false;
        }

        public ComponentMain GetComponent(int coordX, int coordY)
        {
            foreach (ComponentMain c in components)
            {
                if (c.ContainsPoint(coordX, coordY))
                {
                   
                    return c;
                }
            }
            return null;
        }

        public bool RemoveComponent(int coordX, int coordY)
        {
            bool isRemoved = false;
            if (this.GetComponent(coordX, coordY) != null && this.GetComponent(coordX, coordY).ContainsPoint(coordX, coordY) == true)
            {
                components.Remove(this.GetComponent(coordX, coordY));
                isRemoved = true;
            }
            return isRemoved;
        }



        /// <summary>
        /// If this playground has a plate with identity id1 and also a plate with identity id2,
        /// then the id2-plate is added as a neighbor to the id1-plate, and also 
        ///      the id1-plate is added as a neighbor to the id2-plate
        ///      and the returnvalue is true,
        /// else the returnvalue is false. 
        /// </summary>
        /// <param name="id1"></param>
        /// <param name="id2"></param>
        /// <returns></returns>
        public bool AddConnection(ComponentMain component1, ComponentMain component2)
        {
            bool id1Exist = false;
            bool id2Exist = false;

            ComponentMain tempPlate1 = null;
            ComponentMain tempPlate2 = null;

            // loop through all plates in list and check if both id's exist
            foreach (ComponentMain c in components)
            {
                if (c.ID == id1)
                {
                    id1Exist = true;
                    tempPlate1 = c;
                }

                if (c.ID == id2)
                {
                    id2Exist = true;
                    tempPlate2 = c;
                }
            }

            // if both id's do exist add the edge between them
            // do a second loop, might be a better way to implement this
            if (id1Exist && id2Exist)
            {
                if (tempPlate1 is Source && tempPlate2 is Source)
                {
                    MessageBox.Show("abu source");
                }
                else
                {
                    foreach (ComponentMain c in components)
                    {
                        if (c.ID == id1)
                        {
                            if (id1 == id2)
                            {
                                return false;
                            }
                            else
                            {
                                //c.Neighbors.Add(tempPlate2);
                                return true;
                            }
                        }


                        if (c.ID == id2)
                        {
                            if (id1 == id2)
                            {
                                return false;
                            }
                            else
                            {
                                c.Neighbors.Add(tempPlate1);
                                return true;
                            }
                        }
                    }
                }

                return true;
            }

            return false;

        }
        


        public void DrawAllComponents(Graphics gr, ImageList il)
        {
            foreach (ComponentMain c in this.components)
            {
                c.DrawItself(gr, il);
            }
        }

        /// <summary>
        /// All lines (connections, edges) are drawn in black on the graphics gr
        /// </summary>
        /// <param name="gr"></param>
        public void DrawAllLines(Graphics gr)
        {
            foreach (ComponentMain c in this.components)
            {
                foreach (Connection n in c.Connections)
                {
                    gr.DrawLine(Pens.Black, c.X, c.Y, n.SENTComponent.X, n.RECEIVINGComponent.Y);
                    c.setInputsFromConnections(n);
                    ((Gate)c).Calculate();
                    
                }
            }
        }
    }
}
